<?php
/**
 * Copyright 2013 Andrey Tushev and Probasis 
 */
namespace Emos\Editor;

use Emos\Common;

class Settings {
    public $db;
        
    public $name = null;
    public $title = null;
    
    protected $inited = false;
    protected $table = 'settings';
    
    protected $form;
    
    protected $reply = array();

    public $allowUpdate = true;
    
    function __construct() {        
        $this->form = new Form();        
    }    
    
    public function setDb($db) {
        $this->db = $db;
    }   

    public function setTitle($title) {
        $this->title = $title;
    }    
    
    public function addField($name, $label, $field) {
        $this->form->elementSet->add($name, $label, $field);
        return $field;
    }        
    
    function init() {
        if($this->inited) {
            return;
        }
        $this->inited = true;

        if($this->name === null) {
            $this->name = 'Settings';
        }                
        
        $this->form->init();

        
        $controls = $this->form->elementSet->getControls();      
        
        foreach($controls as $control) {
            $control->db = $this->db;
        }              
    }    
    
    protected function initAction() {
        $this->reply['formHtml'] = $this->getFormHtml();
    }    

    protected function getFormAction() {
        $this->reply['formHtml'] = $this->getFormHtml();
    }       
    
    protected function updateAction() {        
        if(!$this->validate()) {        
            $this->reply['invalidFields'] = $this->getFieldsErrors();            
            $this->addMessage(Common::t('incorrect values'), 'error');            
        }
        else {        
            $this->update();  
            $this->addMessage(Common::t('record updated'));
        }
    }     
    
    protected function update() {          
        if(!$this->allowUpdate) {
            throw new \Exception("UPDATE is not allowed");
        }        
        
        $values = $this->db->selectDict("SELECT name, value FROM ?table:name", 'name', 'value', array(
            'table'   => $this->table
        ));            
        $this->form->setValuesFromRecord($values);         
                        
        foreach ($this->form->elementSet->getControls() as $n=>$control) {
            $sqlPairs = $control->update();
            if($sqlPairs !== null) {
                foreach($sqlPairs as $fieldName => $fieldValue) {                    
                    if(key_exists($fieldName, $values)) {
                        $this->db->exec("UPDATE settings SET value=?value WHERE name=?name", array(                        
                            'name'  => $fieldName,
                            'value' => $fieldValue
                        ));                        
                    }
                    else {
                        $this->db->exec("INSERT INTO settings(name, value) VALUES(?name, ?value)", array(                        
                            'name'  => $fieldName,
                            'value' => $fieldValue
                        ));                        
                    }
                }
            }
        }
    }    
    
    protected function validate() {   
        $valid = true;        
        foreach ($this->form->elementSet->getControls() as $control) {
            if($control->isNullPost()) {
                continue;
            }
            
            $control->validate();
            if(!$control->isValid()) {                
                $valid = false;                
            }
        }            
        return $valid;
    }       
    
    protected function getFieldsErrors() {
        $errors = array();
        foreach ($this->form->elementSet->getControls() as $control) {            
            if(!$control->isValid()) {
                $errors[$control->dbName] = $control->getErrorMessage();
            }
        }         
        return $errors;
    }    
    
    protected function getFormHtml() {
        $values = $this->db->selectDict("SELECT name, value FROM ?table:name", 'name', 'value', array(
            'table'   => $this->table
        ));            
        $this->form->setValuesFromRecord($values);   
        
        
        
        $this->form->setHiddenFields(array('action'=>'update'));
        
        $html  = "<form action='' method='post' enctype='multipart/form-data' class='form'>";                
        $html .= "<div class='title'>".Common::plain($this->title)."</div>";
        $html .= $this->form->getHtml();       
        if($this->allowUpdate) {
            $html .= "<div class='buttons'><input type='submit' value='".Common::t('save')."'></div>";                                            
        }
        $html .= "</form>";        
        
        return $html;        
    }
    
    public function ajax() {                
        if(!$this->inited) {
            $this->init();
        }
        
        ob_start();
        
        $this->reply['source'] = 'emosSettings';        
        $this->reply['name'] = $this->name;        
        $this->reply['messagesHtml'] = '';       
        
        
        $action = @$_POST['action'];
        try {
            $methodName = "{$action}Action";
            if(method_exists($this, $methodName)) {                  
                $r = new \ReflectionMethod($this, $methodName);
                $params = array();
                foreach($r->getParameters() as $param) {
                    $name = $param->getName();
                    if(isset($_POST[$name])) {
                       $params[$name] = $_POST[$name];
                    }
                    else {
                        if($param->isDefaultValueAvailable()) {
                            $params[$name] = $param->getDefaultValue();
                        }
                        else {                        
                            throw new \Exception("No obligated parameter '$name' for '$action' action.");
                        }
                    }                
                }            
                                       
                call_user_func_array(array($this, $methodName), $params);                
            }
            else {
                throw new \Exception("Bad action '$action'");
            }
        }
        catch(\Exception $ex) {  
            $this->addMessage(Common::t('exception', array('message'=>Common::plain($ex->getMessage()))), 'error');
            $this->reply['exception'] = $ex->getMessage();
        }
        
        $output = ob_get_clean();
        if($output != '') {
            $this->addMessage('<p><b>PHP output:</b></p> <div class="output">'.Common::plain($output).'</div></pre>');            
        }
        
        header("Content-type: application/json");
        if(defined('JSON_PRETTY_PRINT') && defined('JSON_UNESCAPED_UNICODE')) {
            print json_encode($this->reply, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);        
        }
        else {
            print json_encode($this->reply);        
        }
    }
    
    
    public function addMessage($message, $type='notice') {
        $this->reply['messagesHtml'] .= "<div class='message {$type}'>{$message}</div>";
    }
}